import re

import jsonpath
import pytest
from requests import Response
from jsonschema import validate, ValidationError

from utils.util_logger import logger
from testcase.test_manager import schema_models


class UtilAssert:
    """
        响应断言工具
    """

    @classmethod
    def assert_status_code(cls, real_response: Response, except_data: int):
        """
            接口返回状态码断言:
            real_response: 接口实际返回值
            except_data: 预期响应码，int类型 
        """
        logger.info(f"预期-状态码: {real_response.status_code}")
        logger.info(f"实际-状态码: {except_data}")
        assert real_response.status_code == except_data, logger.error(\
            f"assert_status_code_failure: except: {except_data} real: {real_response.status_code}")

    @classmethod
    def assert_eq(cls, real_response: Response, except_data: dict):
        """
            相等断言：
            real_response: 接口实际返回值
            except_data: 字典格式的数据, 如: {'$.errcode': 0, '$.message': '用户注册成功'}
        """
        json_response = real_response.json()
        for k, v in except_data.items():
            logger.info(f"预期-eq-{k}: {v}")
            logger.info(f"实际-eq-{k}: {jsonpath.jsonpath(json_response, k)[0]}")
            assert jsonpath.jsonpath(json_response, k)[0] == v, logger.error(\
            f"assert_eq_failure: except: {v} real: {jsonpath.jsonpath(json_response, k)[0]}")


    @classmethod
    def assert_exists(cls, real_response: Response, except_data: list):
        """
            存在断言：
            real_response: 接口实际返回值
            except_data: 列表格式的数据, 如: ['access_token']}
        """
        str_response = str(real_response.json())
        for data in except_data:
            res_list = re.findall(data, str_response)
            logger.info(f"预期-exist-{data}: {except_data}")
            logger.info(f"实际-exist-{data}: {res_list}")
            assert res_list != [], logger.error(f"assert_eq_failure: except: {except_data} real: {[]}")

    @classmethod
    def assert_schema_response_model(cls, response: Response, jsonschema_model_string: str):
        """
            使用jsonchema校验接口响应数据
        """
        json_response = response.json()
        jsonschema_model = cls.import_schema_model(jsonschema_model_string)

        try:
            validate(json_response, schema=jsonschema_model)
            logger.info(f"schema模型校验成功!")
        except ValidationError as e:
            logger.error(f"schema模型校验失败!-{e}")
            # schema校验失败时，需要手动将测试用例标记为fail状态
            pytest.fail(reason=f"json_schema校验失败: {e}")
        

    @classmethod
    def import_schema_model(cls, jsonschema_model_string: str) -> dict:
        """
            使用反射机制，将yaml数据中的schema字符串转换为dict格式
        """
        try:    
            jsonschema_model_dict = getattr(schema_models, jsonschema_model_string)
            logger.info(f"获取{jsonschema_model_dict}成功!")
            return jsonschema_model_dict
        except Exception as e:
            logger.error(f"无法从jchema_models中获取到{jsonschema_model_string}")